Palindrome Permutation II

Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.

For example:

Given s = "aabb", return ["abba", "baab"].

Given s = "abc", return [].

Hint:

  1. If a palindromic permutation exists, we just need to generate the first half of the string.
  2. To generate all distinct permutations of a (half of) string, use a similar approach from: Permutations II or Next Permutation.

Solution:

  1. public class Solution {
  2. public List<String> generatePalindromes(String s) {
  3. int odd = 0;
  4. String mid = "";
  5. List<String> res = new ArrayList<>();
  6. List<Character> list = new ArrayList<>();
  7. Map<Character, Integer> map = new HashMap<>();
  8. // step 1. build character count map and count odds
  9. for (int i = 0; i < s.length(); i++) {
  10. char c = s.charAt(i);
  11. map.put(c, map.containsKey(c) ? map.get(c) + 1 : 1);
  12. odd += map.get(c) % 2 != 0 ? 1 : -1;
  13. }
  14. // cannot form any palindromic string
  15. if (odd > 1) return res;
  16. // step 2. add half count of each character to list
  17. for (Map.Entry<Character, Integer> entry : map.entrySet()) {
  18. char key = entry.getKey();
  19. int val = entry.getValue();
  20. if (val % 2 != 0) {
  21. mid += key;
  22. }
  23. for (int i = 0; i < val / 2; i++) list.add(key);
  24. }
  25. // step 3. generate all the permutations O(n!/2)
  26. getPerm(list, mid, new boolean[list.size()], new StringBuilder(), res);
  27. return res;
  28. }
  29. // generate all unique permutation from list
  30. void getPerm(List<Character> list, String mid, boolean[] used, StringBuilder sb, List<String> res) {
  31. if (sb.length() == list.size()) {
  32. // form the palindromic string
  33. res.add(sb.toString() + mid + sb.reverse().toString());
  34. sb.reverse();
  35. return;
  36. }
  37. for (int i = 0; i < list.size(); i++) {
  38. // avoid duplication
  39. if (i > 0 && list.get(i) == list.get(i - 1) && !used[i - 1]) {
  40. continue;
  41. }
  42. if (!used[i]) {
  43. used[i] = true;
  44. sb.append(list.get(i));
  45. getPerm(list, mid, used, sb, res);
  46. sb.deleteCharAt(sb.length() - 1);
  47. used[i] = false;
  48. }
  49. }
  50. }
  51. }